/*
 * Copyright 2025 The JA-SIG Collaborative. All rights reserved. distributed with this file and
 * available online at
 */
package com.lap.auth.application.dept.assembler;

import com.lap.auth.application.dept.command.CreateDeptCmd;
import com.lap.auth.application.dept.command.UpdateDeptCmd;
import com.lap.auth.application.dept.dto.DeptNodeDto;
import com.lap.auth.application.dept.dto.DeptOptionDto;
import com.lap.auth.domain.dept.Dept;
import com.lap.auth.domain.dept.valueobject.StatusType;
import com.lap.auth.domain.shared.tools.BaseConverter;
import com.lap.framework.tools.EnumUtil;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.apache.commons.lang3.StringUtils;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper(componentModel = "spring")
public interface DeptAssembler extends BaseConverter {
  Integer ZERO = 0;

  default Dept create(String code, CreateDeptCmd cmd) {
    String generateCode = (StringUtils.isBlank(cmd.getCode())) ? code : cmd.getCode();
    return new Dept(
        null,
        listToLastInt(cmd.getPidPaths()),
        listToStr(cmd.getPidPaths()),
        generateCode,
        cmd.getName(),
        codeToStatus(cmd.getStatus()),
        cmd.getRemark(),
        cmd.getSortOrder());
  }

  default Dept update(Integer id, String code, UpdateDeptCmd cmd) {
    return new Dept(
        id,
        listToLastInt(cmd.getPidPaths()),
        listToStr(cmd.getPidPaths()),
        code,
        cmd.getName(),
        codeToStatus(cmd.getStatus()),
        cmd.getRemark(),
        cmd.getSortOrder());
  }

  @Mapping(target = "pidPaths", source = "pidPath")
  @Mapping(target = "children", ignore = true)
  DeptNodeDto toDto(Dept dept);

  List<DeptNodeDto> toDtoList(List<Dept> list);

  DeptOptionDto toOptionDto(Dept dept);

  List<DeptOptionDto> toOptionDtoList(List<Dept> list);

  default StatusType codeToStatus(Integer code) {
    return EnumUtil.fromCode(StatusType.class, code);
  }

  default Integer statusToCode(StatusType status) {
    return status.getCode();
  }

  default List<DeptNodeDto> convertToTree(List<DeptNodeDto> allList) {
    List<DeptNodeDto> roots = new ArrayList<>();
    Map<Integer, DeptNodeDto> nodeMap = new HashMap<>();
    for (DeptNodeDto dto : allList) {
      dto.setChildren(new ArrayList<>());
      nodeMap.put(dto.getId(), dto);
    }

    for (DeptNodeDto dto : allList) {
      if (Objects.equals(dto.getPid(), ZERO)) {
        roots.add(dto);
      } else {
        DeptNodeDto parent = nodeMap.get(dto.getPid());
        if (parent != null) {
          parent.getChildren().add(dto);
        }
      }
    }

    for (DeptNodeDto dto : nodeMap.values()) {
      dto.getChildren().sort(Comparator.comparing(DeptNodeDto::getSortOrder));
    }
    roots.sort(Comparator.comparing(DeptNodeDto::getSortOrder));
    return roots;
  }
}
